#include "ring_arrays.h"

struct ring_arrays* ring_arrays_create(void)
{
    return ring_arrays_create_of_size(1024);
}

struct ring_arrays* ring_arrays_create_of_size(uint32_t size)
{
    struct ring_arrays* array = NULL;
    array = (struct ring_arrays*)malloc(sizeof(struct ring_arrays));
    array->size = size;
    array->data = (uint8_t*)malloc(sizeof(uint8_t) * (array->size + 1));
    array->start = 0;
    array->end = 0;
    return array;
}

void ring_arrays_destroy(struct ring_arrays* array)
{
    if (array == NULL) {
        // SIGNWAY_LOGE("array is NULL");
        return;
    } 
    if (array->data != NULL) {
        free(array->data);
        array->data = NULL;
    }
    free(array);
    return;
}

struct uint8_array ring_arrays_get_buffer(struct ring_arrays* array)
{
    struct uint8_array string;
    if (array == NULL) {
        // SIGNWAY_LOGE("array is NULL");
        return string;
    } 
    string.data = array->data + array->start;
    string.length = array->end - array->start;
    array->data[array->end] = '\0';
    return string;
}

BOOL ring_arrays_clear(struct ring_arrays* array)
{
    if (array == NULL) {
        // SIGNWAY_LOGE("array is NULL");
        return FALSE;
    } 
    array->start = 0;
    array->end = 0;
    return TRUE;
}

void ring_arrays_add_buffer(struct ring_arrays* array, uint8_t* buffer, uint32_t len)
{
    if (array == NULL || buffer == NULL || len <= 0) {
        // SIGNWAY_LOGE("array or buffer is NULL or len = %d", len);
        return;
    }
    // SIGNWAY_LOGD("add buffer len = %d, start = %d, end = %d", len, array->start, array->end);
    if (array->end + len > array->size) {
        memmove(array->data, array->data + array->start, array->end - array->start);/* 源内存与目标内存重叠时使用memcpy会出错 */
        array->end = array->end - array->start;
        array->start = 0;
    }
    if (array->end + len > array->size) {
        ring_arrays_clear(array);/* 未处理数据太多 */
    }
    memmove(array->data + array->end, buffer, len);
    array->end += len;
    return;
}

/* 删除缓冲区前offset个数据 */
BOOL ring_arrays_set_offset(struct ring_arrays* array, uint32_t offset)
{
    if (array == NULL) {
        // SIGNWAY_LOGE("array is NULL");
        return FALSE;
    }
    if (array->start + offset <= array->end) {
        array->start += offset;
    }
    return TRUE;
}
